feat: rework clip catalog (group paste, folder metadata, panel polish)#215
Merged
Conversation
Pastes whose root contains <Group> elements now expand into one clip per <Script>, mirroring the Group hierarchy as FolderPath segments. Loose scripts paste at the currently selected clip's folder; Groups nest beneath it. Folder name collisions merge into the existing folder.
- Add FolderData with FileMaker Group attributes (id, includeInMenu, groupCollapsed) - Extend IClipRepository with LoadFoldersAsync/SaveFoldersAsync (default-implemented) - Persist folders as .sharpfm-folder.json sidecars; empty folders survive saves - Capture Group attributes when decomposing a paste; carry forward through the host - Track folder selection in the tree so new clip/folder/paste land in the targeted folder - Add New Folder command to the File menu and tree context menu
Names containing '/', ':', or other reserved characters now round-trip cleanly through the local file-system repository instead of failing the save with a DirectoryNotFoundException or losing folder segments to sanitization.
- Tree context menu mirrors the File/Edit commands so New / Paste / Copy / Rename / Delete work consistently regardless of how the menu was opened - New Script creates a whole-script clip (Mac-XMSC); New Script Steps creates a bare step list (Mac-XMSS), matching the existing Copy-as-... split - Tapping a folder leaves the active editor tab alone; right-clicking empty tree area targets the repository root - New Folder no longer auto-selects the just-created folder, so successive invocations produce siblings instead of nesting
The clip tree now fills the entire left panel via DockPanel layout so empty space below the last node is a valid right-click target for root operations. A single synthetic root node (labeled after the repo's leaf folder) wraps the top-level items, giving root-targeted actions an explicit click target regardless of how much content fills the panel.
The clip tree's IsExpanded property on the VM was never wired to the container, so every RebuildTree triggered by a new clip, paste, or folder operation collapsed the tree back to Avalonia's default. A two-way style setter on TreeViewItem.IsExpanded honours the VM (default true) and routes chevron clicks back to it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Pasting a script
Groupfrom FileMaker decomposes into one clip per<Script>, mirroring the Group hierarchy as folders in the clip repository. Single-clip paste behavior is unchanged.GroupPasteDecomposerwalksfmxmlsnippet, emitting one entry per<Script>plus aFolderDataper<Group>carryingid,includeInMenu, andgroupCollapsed. Returns null when the snippet has no Group so the existing single-clip path is preserved.MainWindowViewModel.PasteFileMakerClipDatabranches on the decomposer's result and lands group pastes relative to the currently selected clip/folder, so the paste appears where the user was looking. Loose scripts alongside a Group share the paste root; nested Groups produce nested folders.(2),(3), …Folder persistence
FolderDatamodel carries Group metadata;IClipRepositorygains default-implementedLoadFoldersAsync/SaveFoldersAsync.ClipRepositorypersists folders as.sharpfm-folder.jsonsidecars; empty folders survive saves and load as standalone tree nodes.Tree UX
TreeViewItem.IsExpandedso expansion state survives rebuilds.Tests
Coverage spans the decomposer (single Group, multiple scripts, nested Groups, loose scripts, attribute capture), the paste handler (group + collision + paste-at-selected-hierarchy), folder persistence + percent-encoding round-trips, and tree-selection behavior. Full suite: 1306 + 101 passing.
Closes #206